#include<set>
#include<vector>
#include"function.h"
using namespace std;
//Global varible
//setting gSetting("setting.xml");

setting::setting(const string &filename)
{
	try
	{
		_Load(filename);
	}
	catch(msg &e)
	{
		simpleio::error("",e);
	}
}
void setting::_Load(const string &filename)
{
	// Create empty property tree object
	using boost::property_tree::ptree;
	ptree pt;

	// Load XML file and put its contents in property tree. 
	// No namespace qualification is needed, because of Koenig 
	// lookup on the second argument. If reading fails, msg
	// is thrown.
	read_xml(filename, pt);

	// Get filename and store it in m_file variable. Note that 
	// we specify a path to the value using notation where keys 
	// are separated with dots (different separator may be used 
	// if keys themselves contain dots). If debug.filename key is 
	// not found, msg is thrown.
	logFile = pt.get<string>("Settings.LogFile");
	output_dir = pt.get<string>("Settings.output_dir");
	circutes_dir = pt.get<string>("Settings.circutes_dir");
	//lfsrs_dir = pt.get<string>("Settings.lfsrs_dir");

	for(auto &v:pt.get_child("Settings.Circutes"))
		circutes.push_back(v.second.data());
	//for(auto &v:pt.get_child("Settings.lfsrs"))
		//lfsrs.push_back(v.second.data());
	//cout<<filename<<":load success\n";
};

void setting::_Save(const string &filename)
{

	// Create empty property tree object
	//using boost::property_tree::ptree;
	//ptree pt;

	// Put log filename in property tree
	//pt.put("debug.filename", m_file);

	// Put debug level in property tree
	//pt.put("debug.level", m_level);

	// Iterate over modules in set and put them in property
	// tree. Note that the add function places new key at the
	// end of list of keys. This is fine in most of the
	// situations. If you want to place item at some other
	// place (i.e. at front or somewhere in the middle),
	// this can be achieved using a combination of the insert
	// and put_value functions
	//BOOST_FOREACH(const std::string &name, m_modules)
	//pt.add("debug.modules.module", name);

	// Write property tree to XML file
	//write_xml(filename, pt);

}


void table::add(const tuple<string,int,int,double>& e)
{
	ptree child; 
	child.add("name",get<0>(e));
	child.add("order",get<1>(e));
	child.add("length",get<2>(e));
	child.add("ratio",get<3>(e));
	_Pt.add_child("modules.module",child);
}


void table::save(const string& filename)
{
	write_xml(filename, _Pt);
}

//0001+0011=00x1
vector<vector<uint8_t>> merge_number(vector<vector<uint8_t>> data) 
{
	vector<vector<uint8_t>> u;//original data
	set<vector<uint8_t>> v(data.begin(),data.end());//generate data;
	//for(auto &e:data)v.insert(e);
	//bool merged=true;
	//cout<<"input:"<<endl;
	//for(auto &e:v)
	//{
		//for(int i=e.size()-1;i>=0;i--)
		//cout<<xmap[e[i]];
		//cout<<endl;
	//}
	while(v.size()>=2)
	{
		//merged=false;
		//print
	
	//cout<<"###"<<endl;
		//u=v;
		u.clear();
		u.assign(v.begin(),v.end());
		v.clear();
		for(int i=0;i<u.size()-1;i++)
			for(int j=i+1;j<u.size();j++)
			{
				int p;
				int size=u[i].size();
				int num=0;
				for(int k=0;k<size;k++)
					if(num<=2&&u[i][k]!=u[j][k])
						{
							p=k;
							num++;							//break;
						}
				//cout<<"k="<<k<<endl;
				if(num==1)//It can be merged
				{
					auto t=u[i];
					t[p]=X;
					v.insert(t);
					//v.back().at(p)=X;
					//cout<<"Merged"<<endl;
					//merged=true;
				}
			}
			//unique(v.begin(),v.end());
		//u=v;
		//v.clear();
	}
	//print
	//cout<<"result:"<<endl;
	if(!v.empty()){ 
	//for(auto &e:u)
	//{
		//for(int i=e.size()-1;i>=0;i--)
		//cout<<xmap[e[i]];
		//cout<<endl;
	//}
	//return u;
	//}
	u.assign(v.begin(),v.end());
	}
	/*for(auto &e:u)
	{
		for(int i=e.size()-1;i>=0;i--)
		cout<<xmap[e[i]];
		cout<<endl;
	}
	cout<<"..."<<endl;
	*/
	return u;
}

vector<uint8_t> merge_number(vector<vector<uint8_t>> data,vector<uint8_t> ref) 
{
	vector<vector<uint8_t>> ret{ref};
	auto add=[&ref,&ret](const vector<uint8_t> &x)
	{
		bool comp=true;
		for(int i=0;i<ref.size();i++)
			if(ref[i]&x[i]==1)
				{
					comp==false;
					break;
				}
		if(comp)
			ret.push_back(x);
	};
	
	vector<vector<uint8_t>> u;//original data
	set<vector<uint8_t>> v(data.begin(),data.end());//generate data;
	//for(auto &e:data)v.insert(e);
	//bool merged=true;
	//cout<<"input:"<<endl;
	//for(auto &e:v)
	//{
		//for(int i=e.size()-1;i>=0;i--)
		//cout<<xmap[e[i]];
		//cout<<endl;
	//}
	while(v.size()>=2)
	{
		//merged=false;
		//print
	
	//cout<<"###"<<endl;
		//u=v;
		u.clear();
		u.assign(v.begin(),v.end());
		v.clear();
		for(int i=0;i<u.size()-1;i++)
			for(int j=i+1;j<u.size();j++)
			{
				int p;
				int size=u[i].size();
				int num=0;
				for(int k=0;k<size;k++)
					if(num<=2&&u[i][k]!=u[j][k])
						{
							p=k;
							num++;							//break;
						}
				//cout<<"k="<<k<<endl;
				if(num==1)//It can be merged
				{
					auto t=u[i];
					t[p]=X;
					v.insert(t);
					add(t);
					//v.back().at(p)=X;
					//cout<<"Merged"<<endl;
					//merged=true;
				}
			}
			//unique(v.begin(),v.end());
		//u=v;
		//v.clear();
	}
	//print
	//cout<<"result:"<<endl;
	//if(!v.empty()){ 
	//for(auto &e:u)
	//{
		//for(int i=e.size()-1;i>=0;i--)
		//cout<<xmap[e[i]];
		//cout<<endl;
	//}
	//return u;
	//}
	//u.assign(v.begin(),v.end());
	//}
	/*for(auto &e:u)
	{
		for(int i=e.size()-1;i>=0;i--)
		cout<<xmap[e[i]];
		cout<<endl;
	}
	cout<<"..."<<endl;*/
	return ret.back();
}

//ofstream logfile(gSetting.logFile);

